package game.leon.engine.utils;

import game.leon.engine.pattern.Filter;
import game.leon.engine.utils.LinkedNode;

import java.util.concurrent.locks.ReentrantLock;

/**
 * User: bianpeng
 * Date: 12-1-12
 * 消息接收
 */
public class Reciever<T> {
    private ReentrantLock lock = new ReentrantLock();
    private LinkedNode<T> queue;
    //
    // 添加一项
    //
    public void recieve(T item) {
        lock.lock();
        try {
            queue = LinkedNode.cons(item, queue);
        } finally {
            lock.unlock();
        }
    }
    //
    // 添加一个list
    //
    public void recieve(LinkedNode<T> node) {
        lock.lock();
        try {
            while (node != null) {
                LinkedNode<T> first = node;
                node = node.getNext();
                first.setNext(queue);
                queue = first;
            }
        } finally {
            lock.unlock();
        }
    }
    //
    // 消费掉当前的消息, 全部
    //
    public LinkedNode<T> consume() {
        if (isEmpty()) return null;
        LinkedNode<T> node = null;
        lock.lock();
        try {
            node = queue;
            queue = null;
        } finally {
            lock.unlock();
        }
        return node;
    }
    //
    // 过滤出所需的消息
    //
    public LinkedNode<T> consume(Filter<T> filter) {
        if (isEmpty()) return null;
        LinkedNode<T> result = null;
        lock.lock();
        try {
            LinkedNode<T> first = queue;
            queue = null;
            while (first != null) {
                LinkedNode<T> it = first;
                first = first.getNext();
                if (filter.test(it.getItem())) {
                    it.setNext(result);
                    result = it;
                } else {
                    it.setNext(queue);
                    queue = it;
                }
            }
        } finally {
            lock.unlock();
        }
        return result;
    }
    public boolean isEmpty() {
        return queue == null;
    }
}
